/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2018-2021.
 * Description: exception prehandler support
 * Author: liujianping <jianping.liu@huawei.com>
 * Create: 2018-09-28
 */

#include <linux/bug.h>
#include <linux/signal.h>
#include <linux/personality.h>
#include <linux/kallsyms.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/hardirq.h>
#include <linux/kdebug.h>
#include <linux/module.h>
#include <linux/kexec.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/syscalls.h>

#include <asm/atomic.h>
#include <asm/bug.h>
#include <asm/debug-monitors.h>
#include <asm/esr.h>
#include <asm/insn.h>
#include <asm/traps.h>
#include <asm/stacktrace.h>
#include <asm/exception.h>
#include <asm/system_misc.h>
#ifdef CONFIG_RTOS_HAL_SRE_PREHANDLER
#include <asm/usr_except.h>
#include <linux/task_struct_extend.h>
#endif
#ifdef CONFIG_RTOS_KBOX
#include <linux/set_kbox_region.h>
#endif

#ifdef CONFIG_RTOS_HAL_SRE_PREHANDLER
int sre_prehandler_register(struct task_struct *task,
	int (*handler)(struct usr_except_args *args))
{
	struct rtos_task_struct *rtos_task = NULL;

	if (task == NULL || handler == NULL) {
		printk(KERN_ERR " task or handler null\n");
		return -EINVAL;
	}

	if (task != current) {
		printk(KERN_ERR "task isn't current\n");
		return -EINVAL;
	}

	rtos_task = task_to_rtos_task(task);
	if (rtos_task->sre_prehandler) {
		printk(KERN_ERR " already registered? pid:%d\n", task_pid_nr(task));
	}

	rtos_task->sre_prehandler = handler;

	return 0;
}
EXPORT_SYMBOL_NS(sre_prehandler_register, HW_RTOS_NS);

int sre_prehandler_unregister(struct task_struct *task)
{
	struct rtos_task_struct *rtos_task = NULL;

	if (!task) {
		printk(KERN_ERR "task struct null\n");
		return -EINVAL;
	}

	if (task != current) {
		printk(KERN_ERR "task isn't current\n");
		return -EINVAL;
	}

	rtos_task = task_to_rtos_task(task);
	if (!rtos_task->sre_prehandler) {
		printk(KERN_ERR " sre_prehandler are NULL\n");
		return -ENODEV;
	}
	rtos_task->sre_prehandler = NULL;
	return 0;
}
EXPORT_SYMBOL_NS(sre_prehandler_unregister, HW_RTOS_NS);
#endif
